package com.ct.ecommerce.authorization.config;

import com.ct.ecommerce.framework.security.JwtTokenEnhancer;
import java.security.KeyPair;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;

/**
 * @author changtong
 * @since 2021/5/29
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {

    @Value("${keyStoreKeyPassword}")
    private String keyStoreKeyPassword;
    @Value("${keyPairName}")
    private String keyPairName;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public JwtTokenEnhancer jwtTokenEnhancer(){
        return new JwtTokenEnhancer();
    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        //对称加密
        //converter.setSigningKey("c2c-e-commerce-oauth");

        //非对称加密
        ClassPathResource resource = new ClassPathResource("cxs-jwt.jks");
        //创建钥匙工厂
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resource,
            keyStoreKeyPassword.toCharArray());
        //通过别名拿钥匙
        KeyPair keyPair = keyStoreKeyFactory.getKeyPair(keyPairName);
        converter.setKeyPair(keyPair);

        return converter;
    }

    /**
     * 配置第三应用 "authorization_code": code授权 "password": 密码授权 "client_credentials": 客户端授权 "implicit":
     * 静默授权
     *
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        /* 密码授权 */
        clients.inMemory()
            /*第三方客户端id */
            .withClient("api_code")
            /*第三方应用密码 */
            .secret(passwordEncoder.encode("api_code_secret"))
            /*第三应用的作用域 */
            .scopes("all")
            /*授权种类 */
            .authorizedGrantTypes("password","refresh_token")
            /*token有效期 */
            .accessTokenValiditySeconds(7200)
            /*刷新令牌有效期 10天*/
            .refreshTokenValiditySeconds(864000);
    }

    /**
     * 配置授权（authorization）以及令牌（token）的访问端点和令牌服务(token services)
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
        /* 配置JWT的内容增强器 */
        enhancerChain.setTokenEnhancers(Arrays.asList(jwtTokenEnhancer(),jwtAccessTokenConverter()));

        endpoints
            .tokenEnhancer(enhancerChain)
            .authenticationManager(authenticationManager)
            .userDetailsService(userDetailsService)
            .accessTokenConverter(jwtAccessTokenConverter());
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer
           // .tokenKeyAccess("permitAll()") //获取公钥接口 url
           // .checkTokenAccess("permitAll()") //资源服务器验证url
            .allowFormAuthenticationForClients();
    }
}
